package com.ayz.gateway.center.infrastructure.nginx.docker;

import com.ayz.gateway.center.infrastructure.nginx.AbstractGatewayServiceDeployer;
import com.ayz.gateway.center.infrastructure.nginx.NgxConfigMetadata;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.async.ResultCallback;
import com.github.dockerjava.api.command.ExecCreateCmdResponse;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.DockerClientConfig;
import lombok.Getter;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName DockerGatewayServiceDeployer
 * @Description TODO: 基于Docker的网关服务部署器
 * NGX 和 api-gateway-center 共同挂载宿主机的文件 ngx.conf
 * api-gateway-center 在配置文件动态更新后
 * 需要调用宿主机的Docker容器管理器 让NGX所在的容器完成NGX配置文件重新装载
 * @Author 快乐的星球
 * @Date 2023/6/12 19:01
 * @Version 1.0
 **/
@Getter
@Setter
public class DockerGatewayServiceDeployer extends AbstractGatewayServiceDeployer {
    /**
     * 安装了Docker的宿主机的DOCKER_HOST的目录
     */
    public static final String DOCKER_HOST="unix:///var/run/docker.sock";
    /**
     * 刷新NGINX配置文件的指令
     */
    public static final String REFRESH_CONFIG_COMMAND="nginx -s reload";

    private static final Logger LOG= LoggerFactory.getLogger(DockerGatewayServiceDeployer.class);
    /**
     * Docker的客户端
     */
    private DockerClient dockerClient;
    public DockerGatewayServiceDeployer(NgxConfigMetadata ngxConfigMetadata) {
        super(ngxConfigMetadata);
    }

    @Override
    public void init() throws IOException {
        super.init();
        //TODO: 完成Docker Client的创建
        LOG.info("开始完成Docker Client的创建!");
        DockerClientConfig clientConfig = DefaultDockerClientConfig.createDefaultConfigBuilder()
                .withDockerHost(DOCKER_HOST).build();

        this.dockerClient = DockerClientBuilder.getInstance(clientConfig).build();
    }

    @Override
    public void refreshNgxConfig() throws Exception {
        LOG.info("完成Nginx容器的配置重新加载!");
        try {
            //1: ngx容器的名称
            String ngxContainerName = getNgxConfigMetadata().getNgxContainerName();
            LOG.info("containerName:{}",ngxContainerName);
            //2: 构建 nginx -s reload 指令
            List<String> nameFilter=new ArrayList<>();
            nameFilter.add(ngxContainerName);
            //3: 相当于执行 docker ps 然后根据名字筛选出 具体的容器 然后获取其容器的ID
            String containerId = dockerClient.listContainersCmd()
                    .withNameFilter(nameFilter)
                    .exec()
                    .get(0).getId();
            LOG.info("containerId:{}",containerId);
            LOG.info("调用Docker容器管理工具进行容器刷新!");
            ExecCreateCmdResponse cmdResponse = dockerClient.execCreateCmd(containerId)
                    .withCmd("nginx","-s","reload").exec();
            dockerClient.execStartCmd(cmdResponse.getId())
                    .exec(new ResultCallback.Adapter<>()).awaitCompletion();
            LOG.info("Nginx容器配置重新加载成功!");
        }catch (Exception ex){
            throw new RuntimeException("nginx容器的配置重新加载失败! 请检查Nginx配置!");
        }
    }

    /**
     * 关闭Docker网关服务的部署器
     * @throws IOException
     */
    public void close()throws IOException{
        this.dockerClient.close();
    }
}
